﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace ANLP.Lexer
{
    internal enum Tokens : int
    {
        Whitespace,
        DoublePercent,
        Code,
        Regex,
        MultipartToken,
        Token,
        SinglePercent,
        StateStart,
        StateEnd,
    }

    public class LexerLexer : ANLP.LexerBase
    {
        protected override void Initialize()
        {
            IDictionary<ANLP.LexerHandler, ANLP.TokenHandler> normalExpressions = new Dictionary<ANLP.LexerHandler, ANLP.TokenHandler>();
            IDictionary<ANLP.LexerHandler, ANLP.TokenHandler> codeDuplication = new Dictionary<ANLP.LexerHandler, ANLP.TokenHandler>();
            IDictionary<ANLP.LexerHandler, ANLP.TokenHandler> codeExpression = new Dictionary<ANLP.LexerHandler, ANLP.TokenHandler>();
            IDictionary<ANLP.LexerHandler, ANLP.TokenHandler> otherThanRegexExpressions = new Dictionary<ANLP.LexerHandler, ANLP.TokenHandler>();
            lexExpressions.Add(0, normalExpressions);
            lexExpressions.Add(1, codeDuplication);
            lexExpressions.Add(2, codeExpression);
            lexExpressions.Add(3, otherThanRegexExpressions);
            AddRegex(normalExpressions, @"\G%%", delegate() { return (int)Tokens.DoublePercent; });
            AddRegex(normalExpressions, @"\G%", delegate() { return (int)Tokens.SinglePercent; });
            AddRegex(normalExpressions, @"\G[ \t\r\n\f\v]", delegate() { return (int)Tokens.Whitespace; });
            AddRegex(codeExpression, @"\G[ \t\r\n\f\v]", delegate() { return (int)Tokens.Whitespace; });
            AddRegex(otherThanRegexExpressions, @"\G[ \t\r\n\f\v]", delegate() { return (int)Tokens.Whitespace; });
            AddRegex(normalExpressions, @"\G(([A-Za-z][A-Za-z0-9]+)\.)+([A-Za-z][A-Za-z0-9]+)", delegate() { return (int)Tokens.MultipartToken; });
            AddRegex(otherThanRegexExpressions, @"\G(([A-Za-z][A-Za-z0-9]+)\.)+([A-Za-z][A-Za-z0-9]+)", delegate() { return (int)Tokens.MultipartToken; });
            AddRegex(normalExpressions, @"\G[A-Za-z][A-Za-z0-9]+", delegate() { return (int)Tokens.Token; });
            AddRegex(otherThanRegexExpressions, @"\G[A-Za-z][A-Za-z0-9]+", delegate() { return (int)Tokens.Token; });
            AddRegex(normalExpressions, @"\G(\\\{|[^ \t\r\n%]| %)([^ {]| [^ {])*", delegate() { return (int)Tokens.Regex; });
            AddRegex(codeExpression, @"\G\{([^{}]*|\{[^}]+\})*\}", delegate() { return (int)Tokens.Code; });

            AddRegex(codeDuplication, @"\G([^%]+|%[^%]+)+", delegate() { return (int)Tokens.Code; });
            AddRegex(codeDuplication, @"\G%%\r?\n", delegate() { return (int)Tokens.DoublePercent; });
        }
    }
}
